﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.IO;
using Servicios;
using Negocio;
using Dominio;
using UI.Miembros;
using Watcher;
using Excepciones;

namespace UI
{
    public partial class FileSystemElements : System.Web.UI.Page
    {
        public string RootDirectory { set; get; }
        public string CurrDirectory { set; get; }
        private List<string> lista = new List<string>();
        //        private string currPath;
        private List<Rol> rolesPermitidos = new List<Rol>();

        FileSystemWatcherListener serviciofsWatch = FileSystemWatcherListener.ObtenerInstancia();

        IIndexService servicioIndices = IndexServiceDataBaseImpl.ObtenerInstancia();

        private enum FileSystemType
        {
            All,
            File,
            Directory
        }
        protected void Page_Load(object sender, EventArgs e)
        {

            if (!IsPostBack)
            {
                Session[ConstantesDeSesion.RootDir] = "//";// +System.Net.Dns.GetHostName();
                Session[ConstantesDeSesion.CurrDir] = "//";
                RootDirectory = Session[ConstantesDeSesion.RootDir].ToString();
                CurrDirectory = RootDirectory;
                CargarCheckBoxListMonitoreados();
                ViewStateMode = System.Web.UI.ViewStateMode.Enabled;
            }
            

            if (Session[ConstantesDeSesion.Usuario] != null)
            {
                Usuario usuario = (Usuario)Session[ConstantesDeSesion.Usuario];
                if (((Security)Session[ConstantesDeSesion.Security]).RolPermitido(usuario.Rol, ConstantesFuncionalidades.FileSystemElements))
                {
                    if (!IsPostBack)
                    {
                        //FileSystemInfo[] fileSystems = GetFileSystemInfos(RootDirectory);

                        currentPathLabel.Text = String.Format("<b>Ruta actual:</b> {0}", RootDirectory);
                        if (CurrDirectory.LastIndexOf("/") > 2)
                            ShowFolderContents();

                    }
                }
                else
                {
                    //Usuario  no autorizado
                    WebUtils.MsgBox("Usuario no Autorizado");
                    Response.Redirect("~/Miembros/Busquedas.aspx");
                }
            }
            else
            {
                //Usuario no autenticado
                WebUtils.MsgBox("Usuario no Autenticado");
                Response.Redirect("~/Login.aspx");
            }
        }

        private void CargarCheckBoxListMonitoreados()
        {
            CheckBoxL_monitoreados.DataSource = Servicios.FileSystemElementServiceDataBaseImpl.ObtenerInstancia().ObtenerDirectorios();
            CheckBoxL_monitoreados.DataTextField = "ObtenerLink";
            CheckBoxL_monitoreados.DataBind();
        }

        private void ShowFolderContents()
        {
            ShowFolderContents(RootDirectory);
        }

        private void ShowFolderContents(string path)
        {
            try
            {
                FileSystemInfo[] fileSystemInfos = GetFileSystemInfos(path);
                fileSystemInfoGridView.DataSource = fileSystemInfos;
                fileSystemInfoGridView.DataBind();

                if (fileSystemInfoGridView.Rows.Count > 0)
                {
                    messageLabel.Text = String.Format("{0} objeto/s encontrado/s.", fileSystemInfos.Length);
                }
                else
                {
                    messageLabel.Text = "No hay archivos ni carpetas en el directorio actual.";
                }
            }
            catch(Exception ex)
            {
                messageLabel.Text = "No se tiene permiso sobre esta carpeta.";
                fileSystemInfoGridView.DataSource = null;
                fileSystemInfoGridView.DataBind();
                Session[ConstantesDeSesion.CurrDir] = ObtenerRuta(path);
            }
            finally
            {
                currentPathLabel.Text = String.Format("<b>Ruta actual:</b> {0}", path);
                //       currPath = path;
                ShownNavigationPath(path);
            }
        }

        private void ShownNavigationPath(string path)
        {
            //Separamos la ruta por barras
            //c:\ <carpeta> \ <carpeta> \
            if (RootDirectory == null)
            {
                int pos = path.LastIndexOf(@"\") + 1;
                string nombre = path.Substring(pos);
                string ruta = ObtenerRuta(path);
                RootDirectory = Session[ConstantesDeSesion.RootDir].ToString();
                if (!Session[ConstantesDeSesion.CurrDir].ToString().Equals(ruta) && nombre!="")
                {
                    CurrDirectory = Session[ConstantesDeSesion.CurrDir].ToString() + "/" + nombre;
                    Session[ConstantesDeSesion.CurrDir] = CurrDirectory;
                }
                else
                {
                    CurrDirectory = Session[ConstantesDeSesion.CurrDir].ToString();
                }
            }
            List<PathInfo> paths = BuildNavigationPath(path);

            pathDataList.DataSource = paths;
            pathDataList.DataBind();
        }

        private string ObtenerRuta(string path)
        {
            string ruta = path.Replace("\\", "/");
            ruta = ruta.Replace("///", "//");
            return ruta;
        }
        private List<PathInfo> BuildNavigationPath(string path)
        {
            List<PathInfo> paths = new List<PathInfo>();
            try
            {
                //Solo queremos navegar desde nuestra carpeta raiz
                string parentPathDivision = path.Substring(RootDirectory.Length, path.Length - RootDirectory.Length);

                //separamos las rutas
                string[] splitPath = parentPathDivision.Split("\\".ToCharArray());


                string fullPath = String.Empty;

                //Mejorar: Agregamos una \ al final si no tiene
                string baseFolderPath = RootDirectory;
                /*if (!RootDirectory.EndsWith(@"\"))
                {
                    baseFolderPath = String.Format(@"{0}\", baseFolderPath);
                }*/

                //Mostrar la carpeta raiz
                paths.Add(new PathInfo("Carpeta raiz: ", RootDirectory));

                //Iteramos sobre las rutas
                foreach (string p in splitPath)
                {
                    if (p != String.Empty)
                    {
                        fullPath += p;
                        if (fullPath != String.Empty)
                        {
                            fullPath += @"\";
                        }
                        paths.Add(new PathInfo(p, baseFolderPath + fullPath));
                    }
                }
            }
            catch (Exception ex)
            {
                WebUtils.MsgBox(ConstantesDeMensajes.ErrorInterno);
            }
            return paths;
        }
        private FileSystemInfo[] GetFileSystemInfos(string path)
        {
            return GetFileSystemInfos(path, FileSystemType.All);
        }

        private FileSystemInfo[] GetFileSystemInfos(string path, FileSystemType fsType)
        {
            DirectoryInfo directoryInfo = new DirectoryInfo(path);
            FileSystemInfo[] fileSystemInfos = null;

            switch (fsType)
            {
                case FileSystemType.File:
                    //Retornamos solo archivos
                    fileSystemInfos = directoryInfo.GetFiles();
                    break;
                case FileSystemType.Directory:
                    //retornamos solo directorios
                    fileSystemInfos = directoryInfo.GetDirectories();
                    break;
                default:
                    //retornamos todo lo que esta adentro de la carpeta
                    fileSystemInfos = directoryInfo.GetFileSystemInfos();
                    break;
            }

            return fileSystemInfos;
        }
        protected void fileSystemInfoGridView_RowDataBound(object sender, GridViewRowEventArgs e)
        {
            if (e.Row.RowType == DataControlRowType.DataRow)
            {
                ImageButton fileSystemTypeButton =
                    (ImageButton)e.Row.FindControl("fileSystemTypeImageButton");

                FileSystemInfo fileSystemInfo = (FileSystemInfo)e.Row.DataItem;

                if (fileSystemInfo is FileInfo)
                {
                    fileSystemTypeButton.ImageUrl = "~/Miembros/imagenes/file_16x16.gif";
                    fileSystemTypeButton.CommandName = "File";

                    FileInfo fileInfo = (FileInfo)fileSystemInfo;

                    //get the file size of the file
                    Label fileSizeLabel = (Label)e.Row.FindControl("fileSizeLabel");
                    fileSizeLabel.Text = DetermineFileSize(fileInfo.Length);
                }
                else
                {
                    fileSystemTypeButton.ImageUrl = "~/Miembros/imagenes/folder_open_16x16.gif";
                    fileSystemTypeButton.CommandName = "Directory";
                }

                fileSystemTypeButton.CommandArgument = fileSystemInfo.FullName;
                fileSystemTypeButton.ToolTip = fileSystemInfo.FullName;
            }
        }

        protected void fileSystemInfoGridView_RowCommand(object sender, GridViewCommandEventArgs e)
        {
            //Ejecutamos el comando
            ImageButton fileSystemTypeButton = (ImageButton)e.CommandSource;
            ExecuteButtonAction(fileSystemTypeButton);
        }


        protected void pathDataList_ItemDataBound(object sender, DataListItemEventArgs e)
        {
            //Chequeamos que el item actual sea de un tipo valido
            if (e.Item.ItemType == ListItemType.Item
                || e.Item.ItemType == ListItemType.AlternatingItem
                || e.Item.ItemType == ListItemType.SelectedItem)
            {
                //Buscamos el linkbutton
                LinkButton pathLinkButton =
                    (LinkButton)e.Item.FindControl("pathLinkButton");

                //Sabemos que es un PathInfo asi que casteamos directamente
                PathInfo pathInfo = (PathInfo)e.Item.DataItem;

                //asignamos los valores a nuestro linkbutton
                pathLinkButton.Text = pathInfo.Name;
                pathLinkButton.ToolTip = pathInfo.FullPath;
                pathLinkButton.CommandArgument = pathInfo.FullPath;
                pathLinkButton.CommandName = "Directory";
            }
        }
        protected void pathLinkButton_Click(object sender, EventArgs e)
        {
            LinkButton pathButton = (LinkButton)sender;
            ExecuteButtonAction(pathButton);
        }

        /// <summary>
        /// Este metodo ejecuta la accion apropiada basandose en el commandname
        /// </summary>
        /// <param name="buttonControl"></param>
        private void ExecuteButtonAction(IButtonControl buttonControl)
        {
            if (buttonControl.CommandName == "File")
            {
                //Si el usuario cliqueo un archivo significa que quiere descargarlo
                // StreamFileToClient(buttonControl.CommandArgument);
            }
            else
            {
                //Es una carpeta, seguro quiere entrar
                ShowFolderContents(buttonControl.CommandArgument);
            }
        }

        /// <summary>
        /// Este metodo determina el "tamanio" del archivo
        /// y lo convierte automaticamente y le agrega segun la convencion de nombre por "tamanio"
        /// </summary>
        /// <param name="fileSize">el "tamanio" del archivo</param>
        /// <returns>el "tamanio" formateado</returns>
        private string DetermineFileSize(long fileSize)
        {
            string convertedFileSize = String.Empty;
            double computedSize = 0;
            if (fileSize == 1)
            {
                convertedFileSize = "1 Byte";
            }
            else if (fileSize > 1 && fileSize <= 1023)
            {
                convertedFileSize = String.Format("{0} Bytes", fileSize);
            }
            else if (fileSize >= 1024 && fileSize < 1048575)
            {
                computedSize = fileSize / 1000.0;
                convertedFileSize = String.Format("{0:0.0} KB", computedSize);
            }
            else if (fileSize >= 1048576 && fileSize < 1073741823)
            {
                computedSize = fileSize / 1000000.0;
                convertedFileSize = String.Format("{0:0.0} MB", computedSize);
            }
            else if (fileSize >= 1073741824)
            {
                // Seguro es un gigabyte. Asumimos que no va a haber archivos que pesen terabytes
                computedSize = fileSize / 1000000.0;
                convertedFileSize = String.Format("{0:0.0} MB", computedSize);
            }

            return convertedFileSize;
        }

        

        
        public class PathInfo
        {
            private string _name;
            private string _fullPath;
            public string Name
            {
                get
                {
                    return _name;
                }
            }
            public string FullPath
            {
                get
                {
                    return _fullPath;
                }
            }

            public PathInfo(string name, string fullPath)
            {
                this._name = name;
                this._fullPath = fullPath;
            }
        }

        protected void ButtonAgregar_Click(object sender, EventArgs e)
        {
            if (fileSystemInfoGridView.Rows.Count != 0)
            {
                foreach (GridViewRow row in fileSystemInfoGridView.Rows)
                {
                    CheckBox cb = (CheckBox)row.FindControl("fileSystemTypeCheck");
                    if (cb != null && cb.Checked)
                    {
                        string nombre = ((Label)row.FindControl("nameLabel")).Text;
                        if (CurrDirectory == null)
                            CurrDirectory = Session[ConstantesDeSesion.CurrDir].ToString();
                        try
                        {
                            FileInfo file = new FileInfo(CurrDirectory + "/" + nombre);

                            serviciofsWatch.Agregar(file);
                            WebUtils.MsgBox("Archivo registrado con exito!");
                            CargarCheckBoxListMonitoreados();
                        }
                        catch (DataBaseException ex) {
                            WebUtils.MsgBox(ex.Message);
                        }
                        catch (Exception ex)
                        {
                            //Si hay excepcion entonces es una carpeta
                            DirectoryInfo dir = new DirectoryInfo(CurrDirectory + "/" + nombre);
                            serviciofsWatch.Agregar(dir);
                            WebUtils.MsgBox("Carpeta registrada con exito!");
                            CargarCheckBoxListMonitoreados();
                        }
                    }
                }
            }
            else {
                WebUtils.MsgBox("Debe seleccionar al menos un archivo o una carpeta");
            }

        }


        protected void Button_path_Click(object sender, EventArgs e)
        {
            if (TextBox_path.Text != "")//validad path existente
            {
                if (TextBox_path.Text.StartsWith("//"))
                {
                    //cambio de server
                    RootDirectory=ObtenerRootDir(TextBox_path.Text);
                    Session[ConstantesDeSesion.RootDir] = RootDirectory;
                    Session[ConstantesDeSesion.CurrDir] = TextBox_path.Text;
                }
                else
                {
                    string rutaAnterior = Session[ConstantesDeSesion.CurrDir].ToString();
                    if(rutaAnterior=="//")
                        CurrDirectory += Session[ConstantesDeSesion.CurrDir].ToString() + TextBox_path.Text;
                    else
                        CurrDirectory += Session[ConstantesDeSesion.CurrDir].ToString() + "/" + TextBox_path.Text;
                }
                Session[ConstantesDeSesion.CurrDir] = CurrDirectory;
                ShowFolderContents(CurrDirectory);
                TextBox_path.Text = "";
            }
            else {
                ShowFolderContents();
            }
        }

        private string ObtenerRootDir(string p)
        {
            string RootDir = "//";
            string path = p.Substring(2);
            int pos = path.IndexOf("/");
            RootDir += path.Substring(0, pos);
            return RootDir;
        }

        protected void Button_borrar_Click(object sender, EventArgs e)
        {
            foreach (ListItem item in CheckBoxL_monitoreados.Items)
            {
                if (item.Selected)
                {
                    FileSystemElement borrar = Servicios.FileSystemElementServiceDataBaseImpl.ObtenerInstancia().ObtenerPorId(Int16.Parse(item.Value));
                    serviciofsWatch.Borrar(borrar);
                }
            }
            CargarCheckBoxListMonitoreados();
        }

    }
}